package com.zl.shirodemo.config;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zl.shirodemo.entity.SysUser;
import com.zl.shirodemo.mapper.SysUserMapper;

@Component
public class UserNamePasswordRealm extends AuthenticatingRealm {
    @Autowired
    private SysUserMapper sysUserMapper;
    
    public UserNamePasswordRealm(CredentialsMatcher matcher, SysUserMapper sysUserMapper) {
        super(matcher);
        this.sysUserMapper = sysUserMapper;
    }
    
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UserNamePasswordToken;
    }
    
    
    /**
     * 如果配置了缓存，
     * 1.登录的时候这个方法在缓存中存储的key是
     * token.getPrincipal
     * @see
     * AuthenticatingRealm#getAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
     * 2.退出的时候删除缓存的key是 subject.getPrincipals().getPrimaryPrincipal()
     * @see AuthenticatingRealm#clearCachedAuthenticationInfo(org.apache.shiro.subject.PrincipalCollection)
     * 所以如果在下面doGetAuthenticationInfo 最后返回值生成AuthenticationInfo的时候第一个参数 principal 和本方法的入参 token的 getPrincipal()不是同一个值，那么最后认证的缓存是删除不了的
     * https://blog.csdn.net/cristianoxm/article/details/111242401
     * 所以增加了上边的resolvePrincipal 方法解决这个问题
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = (String)token.getPrincipal();
        SysUser sysUser = sysUserMapper.selectAllByUsername(userName);
    
        if (sysUser == null) {
            throw new UnknownAccountException("用户名或密码错误");
        }
        
        if(sysUser.getLocked() != null && sysUser.getLocked()){
            throw new LockedAccountException("该用户已经被锁定");   
        }
        
        //全局使用，代替Subject.getPrincipal
        PlatFormContext.currentUser.set(sysUser);
        
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, sysUser.getPassowrd(), sysUser.getRealName());
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(String.valueOf(sysUser.getUserid())));
        
        return simpleAuthenticationInfo;
    }
    
 
}
